package com.user.utils;

import com.user.dao.WeatherDao;
import weka.classifiers.functions.LinearRegression;
import weka.core.Attribute;
import weka.core.DenseInstance;
import weka.core.Instances;
import weka.core.converters.ConverterUtils;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * @Author : Yu
 * @Date 2024/5/20 上午12:56
 */
public class PredictFutureSales {

    public static LinearRegression trainModel(String datasetPath) throws Exception {
        // Load dataset
        ConverterUtils.DataSource source = new ConverterUtils.DataSource(datasetPath);
        Instances dataset = source.getDataSet();
        // Set target variable (last attribute as target variable)
        dataset.setClassIndex(dataset.numAttributes() - 1);

        // Create and train LinearRegression model
        LinearRegression model = new LinearRegression();
        model.buildClassifier(dataset);

        return model;
    }

    public static double predictSales(LinearRegression model, double score, double price) throws Exception {
        // Step 1: Prepare the dataset structure
        ArrayList<Attribute> attributes = new ArrayList<>();
        attributes.add(new Attribute("score"));
        attributes.add(new Attribute("price"));
        // Assuming 'sales' is the target variable
        attributes.add(new Attribute("sales"));

        Instances datasetStructure = new Instances("predictDataset", attributes, 0);
        datasetStructure.setClassIndex(datasetStructure.numAttributes() - 1); // Set 'sales' as the target variable

        // Step 2: Create a new instance for prediction
        double[] values = new double[datasetStructure.numAttributes()];
        values[0] = score; // 未来的评分
        values[1] = price; // 未来的价格
        // Leave the target variable (sales) value unset

        DenseInstance instance = new DenseInstance(1.0, values);

        // Step 3: Associate the new instance with the dataset structure
        instance.setDataset(datasetStructure);

        // Step 4: Make the prediction
        return model.classifyInstance(instance);
    }


    // 预测未来 n 个时期的销量，考虑季节天气因素
    public static List<Double> predictFutureSalesEnhanced(LinearRegression model, double initialScore, double initialPrice, List<WeatherDao> weatherDaos) throws Exception {
        List<Double> futureSalesPredictions = new ArrayList<>();
        double score = initialScore;
        double price = initialPrice;
        double previousSales = 0; // Initialize with a default value if needed

        for (WeatherDao weatherDao : weatherDaos) {
            double precipitation = weatherDao.getPrecipitation();
            double averageTemperature = weatherDao.getAverageTemperature();
            double weatherFactor = 1.0;


            // Adjust weather factor based on daily conditions
            if (averageTemperature < 10 || averageTemperature > 30) weatherFactor = 0.9; // Adjust for temperature
            if (precipitation > 10) weatherFactor *= 0.8; // Adjust for high precipitation

            // Predict sales without weather factor to determine trend
            double predictedSalesWithoutWeather = PredictFutureSales.predictSales(model, score, price);

            // Adjust score and price based on the trend
            // Ensure this is not the first prediction
            if (!futureSalesPredictions.isEmpty()) if (predictedSalesWithoutWeather > previousSales) {
                price += 1;
                score += 0.01;
            } else {
                price -= 0.2;
                score -= 0.05;
            }
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ENGLISH);
            LocalDate date = LocalDate.parse(weatherDao.getDate(), formatter);
            DayOfWeek dayOfWeek = date.getDayOfWeek();
            if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) predictedSalesWithoutWeather *= 0.7;
            else predictedSalesWithoutWeather *= 0.60;

            if (dayOfWeek == DayOfWeek.WEDNESDAY) predictedSalesWithoutWeather *= 0.9;
            // Apply weather factor to the predicted sales
            double predictedSales = predictedSalesWithoutWeather * weatherFactor;
            futureSalesPredictions.add(predictedSales);

            // Update previousSales for the next iteration
            previousSales = predictedSalesWithoutWeather;
        }

        return futureSalesPredictions;
    }

    public static void attr() throws Exception {
        // 定义属性
        ArrayList<Attribute> attributes = new ArrayList<>();
        attributes.add(new Attribute("score")); // 评分
        attributes.add(new Attribute("price")); // 价格
        attributes.add(new Attribute("sales")); // 销量

        // 创建 Instances 对象
        Instances data = new Instances("dish_dataset", attributes, 0);
        data.setClassIndex(data.numAttributes() - 1); // 设置目标变量

        // 添加数据实例
        double[][] values = {
                {4.5, 15.99, 250},
                {3.8, 20, 300},
                {4.9, 25.99, 100},
                {4.2, 14.50, 230},
                {3.5, 7.99, 400},
                {4, 50, 129}
        };

        for (double[] instanceValues : values) data.add(new DenseInstance(1.0, instanceValues));

        // 保存为 ARFF 文件
        BufferedWriter writer = new BufferedWriter(new FileWriter("D:/Desktop/毕业设计/order-java/dish_dataset.arff"));
        writer.write(data.toString());
        writer.close();
    }
}
